<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import useUserStore from '@/store/modules/user'
import { useRouter } from 'vue-router'
import request from '@/utils/request'
import usePermissionStore from '@/store/modules/permission'
import { setToken } from '@/utils/auth'

const router = useRouter()
const userStore = useUserStore()

// 摄像头状态
const cameraActive = ref(false)
const autoDetect = ref(false)
const result = reactive({
  success: false,
  user: null,
  message: ''
})
const currentTime = ref('')

// token
let token = ref('')

// 摄像头元素
let video: HTMLVideoElement | null = null
let overlayCanvas: HTMLCanvasElement | null = null
let captureCanvas: HTMLCanvasElement | null = null
let overlayContext: CanvasRenderingContext2D | null = null
let captureContext: CanvasRenderingContext2D | null = null
let stream: MediaStream | null = null
let autoDetectInterval: ReturnType<typeof setInterval> | null = null

// 初始化摄像头元素
const initCameraElements = () => {
  video = document.getElementById('video') as HTMLVideoElement
  overlayCanvas = document.getElementById('overlayCanvas') as HTMLCanvasElement
  captureCanvas = document.getElementById('captureCanvas') as HTMLCanvasElement
  if (overlayCanvas) overlayContext = overlayCanvas.getContext('2d')
  if (captureCanvas) captureContext = captureCanvas.getContext('2d')
}

// 更新时间
const updateCurrentTime = () => {
  currentTime.value = new Date().toLocaleString('zh-CN')
}

// 开启摄像头
const startCamera = async () => {
  initCameraElements()
  try {
    stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 }, audio: false })
    if (video) video.srcObject = stream
    cameraActive.value = true
    if (video) {
      video.addEventListener('loadedmetadata', () => {
        if (overlayCanvas) overlayCanvas.width = video!.videoWidth, overlayCanvas.height = video!.videoHeight
        if (captureCanvas) captureCanvas.width = video!.videoWidth, captureCanvas.height = video!.videoHeight
      })
    }
    ElMessage.success('摄像头已启动')
  } catch (err: any) {
    console.error('无法访问摄像头:', err)
    ElMessage.error('无法访问摄像头，请检查权限设置')
  }
}

// 关闭摄像头
const stopCamera = () => {
  if (stream) {
    stream.getTracks().forEach(track => track.stop())
    if (video) video.srcObject = null
    cameraActive.value = false
  }
  if (autoDetectInterval) clearInterval(autoDetectInterval)
  autoDetectInterval = null
  autoDetect.value = false
  ElMessage.info('摄像头已停止')
}

// 切换自动识别
const toggleAutoDetect = () => {
  if (!cameraActive.value) {
    ElMessage.warning('请先启动摄像头')
    autoDetect.value = false
    return
  }
  if (autoDetect.value) {
    autoDetectInterval = setInterval(() => captureAndRecognize(), 1000)
    ElMessage.success('自动识别已开启')
  } else {
    if (autoDetectInterval) clearInterval(autoDetectInterval)
    autoDetectInterval = null
    ElMessage.info('自动识别已关闭')
  }
}

// 手动拍照
const manualCapture = () => {
  if (!cameraActive.value) {
    ElMessage.warning('请先启动摄像头')
    return
  }
  captureAndRecognize()
}

// 清除人脸框
const clearFaceOverlay = () => {
  if (overlayContext && overlayCanvas) overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height)
}

// 绘制人脸框
const drawFaceRectangle = (x: number, y: number, width: number, height: number) => {
  if (!overlayContext) return
  overlayContext.strokeStyle = '#00ff00'
  overlayContext.lineWidth = 2
  overlayContext.shadowColor = 'rgba(0, 255, 0, 0.5)'
  overlayContext.shadowBlur = 10
  overlayContext.strokeRect(x, y, width, height)
  overlayContext.shadowBlur = 0
}

const loginWithFaceToken = async (accessToken: string) => {
  try {
    setToken(accessToken)
    // 1. 保存 token
    userStore.token = accessToken
    localStorage.setItem('token', accessToken)
    request.defaults.headers['Authorization'] = `Bearer ${accessToken}`

    // 2. 拉取用户信息
    const res = await userStore.getInfo()
    const user = res.data || res
    userStore.userInfo = {
      ...user,
      userId: user.userId ?? user.id,
      userName: user.userName ?? user.username
    }
    userStore.roles = user.roles || userStore.userInfo.roles?.map(r => r.roleKey) || ['admin']
    userStore.permissions = user.permissions || ['*:*:*']

    // 3. 生成动态路由
    const permissionStore = usePermissionStore()
    const accessRoutes = await permissionStore.generateRoutes()
    accessRoutes.forEach(route => router.addRoute(route))

    // 4. 关键：跳转首页，确保守卫已拿到 roles
    // router.replace('/index') // 直接 replace，不用再加 replace 属性

    router.push('/index') // 直接 replace，不用再加 replace 属性

    ElMessage.success('登录成功！正在跳转...')
  } catch (err) {
    console.error(err)
    ElMessage.error('登录失败，请重试')
    router.replace('/login')
  }
}

// 拍照并识别
const captureAndRecognize = () => {
  if (!cameraActive.value || !video || !captureContext || !overlayContext || !captureCanvas) return

  clearFaceOverlay()
  captureContext.drawImage(video, 0, 0, captureCanvas.width, captureCanvas.height)

  captureCanvas.toBlob(async (blob) => {
    if (!blob) {
      ElMessage.error('图像捕获失败')
      return
    }
    try {
      // 人脸检测（可选）
      const detectFormData = new FormData()
      detectFormData.append('faceImage', blob, 'capture.jpg')
      const detectResponse = await fetch('http://localhost:9033/api/face/detect', { method: 'POST', body: detectFormData })
      if (!detectResponse.ok) throw new Error('检测接口错误')
      const faceData = await detectResponse.json()
      faceData.forEach((face: any) => drawFaceRectangle(face.rect.left, face.rect.top, face.rect.right - face.rect.left, face.rect.bottom - face.rect.top))

      // 人脸识别登录
      const recognizeFormData = new FormData()
      recognizeFormData.append('faceImage', blob, 'capture.jpg')
      const response = await fetch('http://localhost:9033/api/face/login', { method: 'POST', body: recognizeFormData })
      if (!response.ok) throw new Error('识别接口错误')
      const data = await response.json()
      console.log('人脸识别结果:', data)
      updateCurrentTime()

      if (data.success && data.tokenInfo?.access_token) {
        token.value = data.tokenInfo.access_token
        loginWithFaceToken(token.value)
      } else {
        result.success = false
        result.message = data.message || '人脸识别失败'
        ElMessage.error(result.message)
      }
    } catch (error: any) {
      console.error('识别请求失败:', error)
      result.success = false
      result.message = '网络请求失败: ' + error.message
      ElMessage.error(result.message)
    }
  }, 'image/jpeg', 0.8)
}

// 返回登录页面
const goBackLogin = () => {
  router.push({ path: '/login' })
}

// 卸载清理
onUnmounted(() => stopCamera())
onMounted(() => initCameraElements())
</script>

<template>
  <div class="container">
    <div class="header">
      <h1>人脸识别系统</h1>
      <p>自动识别模式 - 对准摄像头即可识别</p>
    </div>

    <div class="camera-container">
      <video id="video" class="camera-video" autoplay playsinline></video>
      <canvas id="overlayCanvas" class="face-overlay"></canvas>
      <canvas id="captureCanvas" style="display: none;"></canvas>
    </div>

    <div class="auto-detect-label">
      <el-switch
          v-model="autoDetect"
          active-text="自动识别已开启"
          inactive-text="自动识别已关闭"
          @change="toggleAutoDetect">
      </el-switch>
    </div>

    <div class="action-buttons">
      <el-button type="primary" @click="startCamera" :disabled="cameraActive">
        <span class="status-indicator" :class="cameraActive ? 'status-active' : 'status-inactive'"></span>
        {{ cameraActive ? '摄像头运行中' : '启动摄像头' }}
      </el-button>
      <el-button type="danger" @click="stopCamera" :disabled="!cameraActive">停止摄像头</el-button>
      <el-button type="success" @click="manualCapture" :disabled="!cameraActive">手动识别</el-button>
      <el-button type="info" @click="goBackLogin">返回登录</el-button>
    </div>

    <div class="result-section" v-if="result.message || result.user">
      <h3>识别结果</h3>
      <el-alert
          :type="result.success ? 'success' : 'error'"
          :title="result.message"
          show-icon>
      </el-alert>

      <div class="user-info" v-if="result.user && result.success">
        <img :src="result.user.faceImageUrl" alt="用户头像" class="user-avatar" v-if="result.user.faceImageUrl">
        <div>
          <p><strong>欢迎,</strong> {{ result.user.username }}</p>
          <p><strong>用户ID:</strong> {{ result.user.id }}</p>
          <p><strong>识别时间:</strong> {{ currentTime }}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.container {
  max-width: 800px;
  margin: 0 auto;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 30px;
}
.header { text-align: center; margin-bottom: 30px; }
.camera-container { position: relative; text-align: center; margin-bottom: 30px; }
.camera-video { width: 100%; max-width: 640px; height: 480px; background-color: #000; border-radius: 8px; object-fit: cover; }
.face-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
.action-buttons { text-align: center; margin: 20px 0; }
.result-section { margin-top: 30px; padding: 20px; background-color: #f9f9f9; border-radius: 8px; }
.user-info { display: flex; align-items: center; margin-top: 20px; }
.user-avatar { width: 100px; height: 100px; border-radius: 50%; margin-right: 20px; object-fit: cover; }
.status-indicator { display: inline-block; width: 12px; height: 12px; border-radius: 50%; margin-right: 8px; }
.status-active { background-color: #67c23a; }
.status-inactive { background-color: #f56c6c; }
.auto-detect-label { display: flex; align-items: center; justify-content: center; margin: 15px 0; }
</style>
